#include "stdafx.h"
#include "net/URI.hpp"
#include "net/HTTPCookie.hpp"
#include "utils/numberparser.hpp"
#include "utils/numberformatter.hpp"
using JHCPP::utils::CNumberParser;
using JHCPP::utils::CNumberFormatter;
#include "stdlib/datetime.hpp"
#include "stdlib/timestamp.hpp"
#include "stdlib/datetimeparser.hpp"
#include "stdlib/datetimeformat.hpp"
#include "stdlib/datetimeformatter.hpp"
using JHCPP::stdlib::CDateTime;
using JHCPP::stdlib::CTimeStamp;
using JHCPP::stdlib::CDateTimeParser;
using JHCPP::stdlib::CDateTimeFormat;
using JHCPP::stdlib::CDateTimeFormatter;
#include "charset/string.hpp"
using JHCPP::charset::icompare;

NET_NAMESPACE_BEGIN

CHTTPCookie::CHTTPCookie()
	: m_version(0),
	m_secure(false),
	m_maxAge(-1),
	m_httpOnly(false)
{
}

CHTTPCookie::CHTTPCookie(const std::string& name)
	: m_version(0),
	m_name(name),
	m_secure(false),
	m_maxAge(-1),
	m_httpOnly(false)
{
}

CHTTPCookie::CHTTPCookie(const CNameValueCollection& nvc)
	: m_version(0),
	m_secure(false),
	m_maxAge(-1),
	m_httpOnly(false)
{
	for (CNameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it)
	{
		const std::string& name  = it->first;
		const std::string& value = it->second;
		if (icompare(name, "comment") == 0)
		{
			setComment(value);
		}
		else if (icompare(name, "domain") == 0)
		{
			setDomain(value);
		}
		else if (icompare(name, "path") == 0)
		{
			setPath(value);
		}
		else if (icompare(name, "priority") == 0)
		{
			setPriority(value);
		}
		else if (icompare(name, "max-age") == 0)
		{
			setMaxAge(CNumberParser::parse(value));
		}
		else if (icompare(name, "secure") == 0)
		{
			setSecure(true);
		}
		else if (icompare(name, "expires") == 0)
		{
			int tzd;
			CDateTime exp = CDateTimeParser::parse(value, tzd);
			CTimeStamp now;
			setMaxAge((int) ((exp.timestamp() - now) / CTimeStamp::resolution()));
		}
		else if (icompare(name, "version") == 0)
		{
			setVersion(CNumberParser::parse(value));
		}
		else if (icompare(name, "HttpOnly") == 0)
		{
			setHttpOnly(true);
		}
		else
		{
			setName(name);
			setValue(value);
		}
	}
}

CHTTPCookie::CHTTPCookie(const std::string& name, const std::string& value)
	: m_version(0),
	m_name(name),
	m_value(value),
	m_secure(false),
	m_maxAge(-1),
	m_httpOnly(false)
{
}

CHTTPCookie::CHTTPCookie(const CHTTPCookie& cookie)
	: m_version(cookie.m_version),
	m_name(cookie.m_name),
	m_value(cookie.m_value),
	m_comment(cookie.m_comment),
	m_domain(cookie.m_domain),
	m_path(cookie.m_path),
	m_priority(cookie.m_priority),
	m_secure(cookie.m_secure),
	m_maxAge(cookie.m_maxAge),
	m_httpOnly(cookie.m_httpOnly)
{
}

CHTTPCookie::~CHTTPCookie()
{
}

CHTTPCookie& CHTTPCookie::operator = (const CHTTPCookie& cookie)
{
	if (&cookie != this)
	{
		m_version  = cookie.m_version;
		m_name     = cookie.m_name;
		m_value    = cookie.m_value;
		m_comment  = cookie.m_comment;
		m_domain   = cookie.m_domain;
		m_path     = cookie.m_path;
		m_priority = cookie.m_priority;
		m_secure   = cookie.m_secure;
		m_maxAge   = cookie.m_maxAge;
		m_httpOnly = cookie.m_httpOnly;
	}
	return *this;
}

void CHTTPCookie::setVersion(int version)
{
	m_version = version;
}

int CHTTPCookie::getVersion() const
{
	return m_version;
}

void CHTTPCookie::setName(const std::string& name)
{
	m_name = name;
}

const std::string& CHTTPCookie::getName() const
{
	return m_name;
}

void CHTTPCookie::setValue(const std::string& value)
{
	m_value = value;
}

const std::string& CHTTPCookie::getValue() const
{
	return m_value;
}

void CHTTPCookie::setComment(const std::string& comment)
{
	m_comment = comment;
}

const std::string& CHTTPCookie::getComment() const
{
	return m_comment;
}

void CHTTPCookie::setDomain(const std::string& domain)
{
	m_domain = domain;
}

const std::string& CHTTPCookie::getDomain() const
{
	return m_domain;
}

void CHTTPCookie::setPath(const std::string& path)
{
	m_path = path;
}

const std::string& CHTTPCookie::getPath() const
{
	return m_path;
}

void CHTTPCookie::setPriority(const std::string& priority)
{
	m_priority = priority;
}

const std::string& CHTTPCookie::getPriority() const
{
	return m_priority;
}

void CHTTPCookie::setSecure(bool secure)
{
	m_secure = secure;
}

bool CHTTPCookie::getSecure() const
{
	return m_secure;
}

void CHTTPCookie::setMaxAge(int maxAge) 
{
	m_maxAge = maxAge;
}

int CHTTPCookie::getMaxAge() const
{
	return m_maxAge;
}

void CHTTPCookie::setHttpOnly(bool flag)
{
	m_httpOnly = flag;
}

bool CHTTPCookie::getHttpOnly() const
{
	return m_httpOnly;
}

std::string CHTTPCookie::toString() const
{
	std::string result;
	result.reserve(256);
	result.append(m_name);
	result.append("=");
	if (m_version == 0)
	{
		// Netscape cookie
		result.append(m_value);
		if (!m_domain.empty())
		{
			result.append("; domain=");
			result.append(m_domain);
		}

		if (!m_path.empty())
		{
			result.append("; path=");
			result.append(m_path);
		}

		if (!m_priority.empty())
		{
			result.append("; Priority=");
			result.append(m_priority);
		}

		if (m_maxAge != -1)
		{
			CTimeStamp ts;
			ts += m_maxAge * CTimeStamp::resolution();
			result.append("; expires=");
			CDateTimeFormatter::append(result, ts, CDateTimeFormat::HTTP_FORMAT);
		}

		if (m_secure)
		{
			result.append("; secure");
		}
		if (m_httpOnly)
		{
			result.append("; HttpOnly");
		}
	}
	else
	{
		// RFC 2109 cookie
		result.append("\"");
		result.append(m_value);
		result.append("\"");
		if (!m_comment.empty())
		{
			result.append("; Comment=\"");
			result.append(m_comment);
			result.append("\"");
		}

		if (!m_domain.empty())
		{
			result.append("; Domain=\"");
			result.append(m_domain);
			result.append("\"");
		}

		if (!m_path.empty())
		{
			result.append("; Path=\"");
			result.append(m_path);
			result.append("\"");
		}

		if (!m_priority.empty())
		{
			result.append("; Priority=\"");
			result.append(m_priority);
			result.append("\"");
		}

		if (m_maxAge != -1)
		{
			result.append("; Max-Age=\"");
			CNumberFormatter::append(result, m_maxAge);
			result.append("\"");
		}

		if (m_secure)
		{
			result.append("; secure");
		}

		if (m_httpOnly)
		{
			result.append("; HttpOnly");
		}
		result.append("; Version=\"1\"");
	}
	return result;
}

static const std::string ILLEGAL_CHARS("()[]/|\\',;");

std::string CHTTPCookie::escape(const std::string& str)
{
	std::string result;
	CURI::encode(str, ILLEGAL_CHARS, result);
	return result;
}

std::string CHTTPCookie::unescape(const std::string& str)
{
	std::string result;
	CURI::decode(str, result);
	return result;
}


NET_NAMESPACE_END
